package tms.model;

import java.util.ArrayList;
import java.util.List;

/**
 * The class Person represents a person supposed to carry out a Task.
 * 
 * @author Rolf Schmidt
 * @version 2.0
 */
public class Person extends AbstractModelObject {

	/**
	 * contains number of hours in a working day
	 */
	public static final int HOURS_IN_WORKING_DAY = 8;

	/**
	 * contains the name of the person
	 */
	private String name;
	/**
	 * contains the number of hours all the tasks this person is associated with
	 * will take to complete
	 */
	private int hours;
	/**
	 * contains a list of the task IDs this person is associated with
	 */
	private List<Task> tasks;

	/**
	 * default constructor
	 */
	public Person() {
		super();
		this.name = "nobody";
		this.hours = 0;
		this.tasks = new ArrayList<Task>();
	}

	@Override
	/**
	 * converts the person object to a string.
	 * the string contains the name of each person attribute followed by its value,
	 * and it starts and ends with a separator.
	 * Also there is one attribute on each line  
	 * 
	 * @return the string representation of this person
	 */
	public String toString() {
		final String H_LINE = "---------------------------------------";
		StringBuffer sb = new StringBuffer(H_LINE);

		sb.append("\nName: " + name);
		sb.append("\nHours: " + hours);
		sb.append("\nTasks: " + getTasklist());
		sb.append("\n" + H_LINE + "\n");
		return sb.toString();
	}

	@Override
	/**
	 * evaluates whether this person is equal to another person 
	 * two persons are equal if all of their attributes are equal
	 * 
	 * @param obj an object to use for comparison
	 * 
	 * @return true if and only if this person is identical to the passed Object
	 */
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Person other = (Person) obj;
		if (hours != other.hours)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		if (tasks == null) {
			if (other.tasks != null)
				return false;
		} else if (!tasks.equals(other.tasks))
			return false;
		return true;
	}

	/**
	 * getter of the name of the person
	 * 
	 * @return the name
	 */
	public String getName() {
		return name;
	}

	/**
	 * setter of the name of the person
	 * If the new name is null or empty, then the assigned name will be nobody
	 * Also if the setting of the name is successful, it fires a name change
	 * property event
	 * 
	 * @param name
	 *            the name to set
	 */
	public void setName(String name) {
		String oldValue = this.name;
		if (name == null || name.equals("")) {
			this.name = "nobody";
		} else {
			this.name = name;
		}
		firePropertyChange("name", oldValue, this.name);
	}

	/**
	 * getter of the hours this person is assigned
	 * It is the total of hours of the tasks this person is assigned to
	 * 
	 * @return the hours
	 */
	public int getHours() {
		return hours;
	}

	/**
	 * getter of the tasks this person is assigned to
	 * 
	 * @return the list of task IDs associated with this Person as an ArrayList
	 *         of Tasks
	 */
	public List<Task> getTasks() {
		return this.tasks;
	}

	/**
	 * getter of the tasks this person is assigned to as a string
	 * where the task names are separated by a string
	 * 
	 * @return the list of task IDs associated with this Person as a String
	 */
	public String getTasklist() {
		String result = "";

		int count = 0;
		int size = tasks.size();
		for (; count < size; count++) {
			result += tasks.get(count).getId();
			if (count < size - 1)
				result += ", ";
		}
		return result;
	}

	/**
	 * adds a task and calculates the total number of hours
	 * If the task to be added is null or already exists, then it will not be
	 * added
	 * Also if the task to be added is assigned to a person other that this
	 * person, then
	 * the assignee of the task will be changed to this person.
	 * In addition, the hours associated with the task will be added to the
	 * total number of hours of this person
	 * and an hour change property event will be fired
	 * 
	 * @param task
	 *            the task to add
	 */
	public void addTask(Task task) {
		if (task == null)
			return;

		if (tasks.contains(task))
			return;

		if (!task.getPerson().equals(name))
			task.setPerson(name);

		tasks.add(task);
		int oldVal = this.hours;
		if (!task.hasParent()) {
			this.hours += task.getDuration() * HOURS_IN_WORKING_DAY;
		}
		firePropertyChange("hours", oldVal, this.hours);
		firePropertyChange("tasklist", null, this);
	}
}